/// <reference path="zepto.js" />
var $H;
var Hobbit = window.Hobbit = window.$H = (function () {
    $H = function () { };
    $H.config = {};
  $H.detect = function (ua) {
    ua = ua || navigator.userAgent;
    var match = function (k) {
        var t = "unknown", v = 0;
        for (var m, i = 0; i < k.length; i++)
            //判断版本的通用正则是：\\D*(\\d+[._]?\\d*)?
            if (m = ua.match(new RegExp("(" + k[i][1] + ")\\D*(\\d+[._]?\\d*)?", "i"))) {
                t = k[i][0];
                v = parseFloat(m[2]);
                v = isNaN(v) ? 0 : v;
                break;
            }
        return { type: t, ver: v };
    };
    var os = match([["android", "Android"], ["iosipad", "iPad"], ["iosipod", "iPod"], ["iosiphone", "iPhone\\sOS"], ["windowsmobile", "Windows\\s?Mobile"], ["windowsphone", "Windows\\s?Phone|WPOS"], ["windowspc", "Windows"], ["symbian", "Series60|Symbian|Nokia"], ["blackberry", "BlackBerry"], ["macpc", "Macintosh|Mac\\s?OS"]]);
    var bs = match([["chrome", "Chrome|CriOS"], ["ie", "MSIE"], ["weixin", "MicroMessenger"], ["miuiyp", "MiuiYellowPage"], ["qq", "QQBrowser"], ["uc", "UCBrowser|UCWEB|JUC|\\sUC\\s"], ["firefox", "Firefox"], ["opera", "Opera"], ["safari", "Mac\\s?OS.*Safari"], ["native", "Android.*WebKit"]]);
    return { os: os.type, ov: os.ver, bs: bs.type, bv: bs.ver };
  };
  $H.os = {
    type: function () { return $H.detect().os; },
    ver: function () { return $H.detect().ov; },
    online: function () { return navigator.onLine; }
  };
  $H.browser = {
    ua: navigator.userAgent,
    type: function () { return $H.detect().bs; },
    ver: function () { return $H.detect().bv; },
    height: function () { return $(window).height(); },
    width: function () { return $(window).width(); },
    hideAddressBar: function () {
      //if($.browser.webkit)
      $H.browser.scrollTop();
    },
    scrollTop: function (zep, offset) {
      if (zep)
        window.scrollTo(0, zep.offset().top + (offset || 0));
      else window.scrollTo(0, (offset || 1));
    },
    discrollable: function (selector) {
      var zep = selector ? $(selector) : $(window);
      //zep.bind("touchmove", $H.browser.preventEvent);
      var s = document.body.style; s.overflowX = s.overflowY = "hidden";
    },
    scrollable: function (selector) {
      var zep = selector ? $(selector) : $(window);
      //zep.unbind("touchmove", $H.browser.preventEvent);
      var s = document.body.style; s.overflowX = s.overflowY = null;
    },
    preventEvent: function (e) {
      e.preventDefault();
    }
  };
  $H.json = {
    stringify: function (json) {
      var s = null;
      try {
        s = window.JSON.stringify(json);
      }
      catch (e) {
        console.error(e);
      }

      return s;
    },
    parse: function (string) {
      var j = null;
      try {
        j = window.JSON.parse(string);
      }
      catch (e) {
        console.error(e);
      }

      return j;
    }
  };
  $H.url = {
    parse: function (href) {
      var data = {
        href: "",
        host: "",
        hostname: "",
        pathname: "",
        port: "",
        query: {},
        hash: "",
        search: ""
      };

      function dotQuery(href) {
        var num = 0;
        for (var i = 0; i < href.length; i++) {
          if (href.charAt(i) == ".") {
            num++;
          } else {
            return num;
          }
        }
      }

      function relativeUrl(href) {
        var reg = /^(\.{0,}\/{0,})/,
        dot = dotQuery(href),
        newUrl = "";

        if (dot < 2) {
          newUrl = currUrl.href.split("://")[0] + "://" + currUrl.host + currUrl.pathname + href.replace(reg, "");
        } else {
          var currUrlArr = [];
          currUrlArr = currUrl.pathname.split("/");

          if (currUrlArr.length - 2 > dot - 1) {
            var newPath = "/";
            for (var i = 1; i < currUrlArr.length - dot - 2; i++) {
              newPath += currUrlArr[i] + "/";
            };
            newUrl = currUrl.href.split("://")[0] + "://" + currUrl.host + newPath + href.replace(reg, "");
          } else {
            newUrl = currUrl.href.split("://")[0] + "://" + currUrl.host + "/" + href.replace(reg, "");
          }
        }
        return newUrl;
      }

      var currUrl = window.location;
      if (href && href.length > 0) {
        var domainReg = /^\w+\./;
        if (href.split("://")[1]) {
          data.href = href;
        } else if (domainReg.test(href)) {
          data.href = currUrl.href.split("://")[0] + "://" + href;
        } else {
          data.href = relativeUrl(href);
        }

        var urlArr = data.href.split("?");

        data.hostname = urlArr[0].split("://")[1].split(/\:|\/|\#/)[0];
        data.port = data.href.split(":")[2] ? data.href.split(":")[2].split(/\/|\?|\#/)[0] : "";
        data.host = data.port ? data.hostname + ":" + data.port : data.hostname;
        data.pathname = data.href.split("://")[1].substring(data.host.length).split(/\?|\#/)[0];
        data.hash = data.href.split("#")[1] ? "#" + data.href.split("#")[1] : "";
        data.search = urlArr[1] ? "?" + urlArr[1].split("#")[0] : "";
        data.query = $H.url.query(data.href);
                //  正则表达式版本敬请期待
        } else {
          data.href = currUrl.href;
          data.host = currUrl.host;
          data.hostname = currUrl.hostname;
          data.pathname = currUrl.pathname;
          data.port = currUrl.port;
          data.hash = currUrl.hash;
          data.search = currUrl.search;
          data.query = $H.url.query(data.href);
      };

      return data;
  },
  href: function (url, query, hash) {
    var url = url ? url : window.location.href,
    query = query || {},
    currQuery = $H.url.parse(url).query,
    newUrl = "",
    newQuery = "",
    newHash = "";

    function isEmpty(obj) {
      for (var i in obj)
        return false;
      return true;
    }
    if (!isEmpty(currQuery)) {
      for (var i in query) {
        for (var j in currQuery) {
          if (i == j) {
            currQuery[j] = query[i];
          } else {
            currQuery[i] = query[i];
          };
        }
      }
    } else {
      currQuery = query;
    };
    for (var k in currQuery) {
      currQuery[k] = currQuery[k] || "";
      newQuery += k + "=" + currQuery[k] + "&";
    }
    newQuery = newQuery.substring(0, newQuery.length - 1);
    newUrl = newQuery ? url.split(/\?|\#/)[0] + "?" + newQuery : url.split("?")[0];

    if (typeof (hash) == undefined) {
      newHash = url.split("#")[1] ? "#" + url.split("#")[1] : "";
      newUrl = newUrl + newHash;
    } else {
      newHash = hash ? "#" + hash : "";
      newUrl = newUrl + newHash;
    };

    return newUrl;
  },
  query: function (href) {
    var args = {},
    queryArr = [],
    queryArrItem = [],
    name, value,
    href = href || window.location.href,
    queryStr = href.split("?")[1] ? href.split("?")[1].split("#")[0] ? href.split("?")[1].split("#")[0] : "" : "";
    if (queryStr == "") {
      return {};
    } else {
      queryArr = queryStr.split("&");
      for (var i = queryArr.length - 1; i >= 0; i--) {
        queryArrItem = queryArr[i].split("=");
        name = decodeURIComponent(queryArrItem[0]);
        value = decodeURIComponent(queryArrItem[1]);
        args[name] = value || "";
      };
      return args;
    };
    }
  };
  $H.hash = function (string) {
      var hash = 1315423911, i, ch;
      for (i = string.length - 1; i >= 0; i--) {
          ch = string.charCodeAt(i);
          hash ^= ((hash << 5) + ch + (hash >> 2));
      }
      return (hash & 0x7FFFFFFF);
  };
  $H.cookie = {
      get: function (key) {
          if (!key)
              return null;
          key = key.toUpperCase();
          var cks = document.cookie.split("; ");
          var tmp = null;
          for (var i = 0; i < cks.length; i++) {
              tmp = cks[i].split("=");
              if (tmp[0].toUpperCase() == key)
                  return unescape(tmp[1]);
          }
          return null;
      },
      set: function (options) {
          options = $.extend({
              key: "",
              value: "",
              expires: 0,
              path: "",
              domain: document.domain
          }, options);

          var ck = [options.key + "=" + escape(options.value)];
          if (!isNaN(options.expires) && options.expires != 0) {//为0时不设定过期时间，浏览器关闭时cookie自动消失
              var date = new Date();
              date.setTime(date.getTime() + options.expires * 60 * 1000);
              ck.push(";expires=" + date.toUTCString());
          }

          ck.push(";path=" + (options.path || "/"));
          if (options.domain && options.domain.toLowerCase() !== "localhost")
              ck.push(";domain=" + options.domain);
          document.cookie = ck.join("");
      },
      remove: function (options) {
          options = $.extend({
              key: "",
              path: "",
              domain: document.domain
          }, options);
          var date = new Date();
          date.setTime(date.getTime() - 999999);
          options.expires = date;
          $H.cookie.set(options);
          //document.cookie = options.key + "=;expires=" + date.toGMTString() + ";path=" + (options.path || "/") + ";domain=" + ((options.domain) || document.domain);
      }
    };
    $H.storage = {
      self: window.localStorage,
      setCnts: 0,
      get: function (key) {
        var ls = $H.storage.self;

        if (key && ls) {
          if (key.length > 64) key = $H.hash(key);

          //浏览器关闭 localStorage
          var value = null;
          try {
            value = ls.getItem(key);
          }
          catch (e) {
            console.error(e);
          }

          var item = $H.json.parse(value);

          if (item && item.exp && !isNaN(item.exp) && item.exp < new Date().getTime()) {
            $H.storage.remove(key);
            return null;
          }

          return item && item.val;
        }
        return null;
      },
      set: function (options) {
        options = $.extend({
          key: null,
          value: "",
          expires: ""
        }, options);

        var ls = $H.storage.self;
        if (options.key && ls) {
          if (++$H.storage.setCnts % 20 == 0)
            $H.storage.recycle();

          options = options || {};

          if (!options.expires)
              options.expires = 3600*24*7;//保存一天

            if (options.key.length > 64)
              options.key = $H.hash(options.key);

            var item = {
              exp: (options.expires * 1000) + new Date().getTime(),
              val: options.value
            };
          //浏览器关闭 localStorage
          try {
            ls.setItem(options.key, $H.json.stringify(item));
          }
          catch (e) { console.error(e); }
        }
      },
      remove: function (key) {
        var ls = $H.storage.self;
        if (ls) {
          if (key.length > 64) key = $H.hash(key);

          //浏览器关闭 localStorage
          try {
            ls.removeItem(key);
          }
          catch (e) { console.error(e); }
        }
      },
      recycle: function () {
        var ls = $H.storage.self;
        if (ls) {
          for (var i = 0; i < ls.length; i++) {
            var key = ls.key(i);

            var value = ls.getItem(key);
            var item = $H.json.parse(value);
            if (item && item.exp && !isNaN(item.exp) && item.exp < new Date().getTime())
              $H.storage.remove(key);
          }
        }
      },
      clear: function () {
        var ls = $H.storage.self;
        if (ls) {
          //浏览器关闭 localStorage
          try {
            ls.clear();
          }
          catch (e) { console.error(e); }
        }
      }
    };
    $H.session = {
      self: window.sessionStorage,
      get: function (key) {
        var ss = $H.session.self;
        if (key && ss) {
          if (key.length > 64) key = $H.hash(key);

          //浏览器关闭 sessionStorage
          var value = null;
          try {
            value = ss.getItem(key);
          }
          catch (e) {
            console.error(e);
          }

          return value;
        }
        return null;
      },
      set: function (options) {
        options = $.extend({
          key: null,
          value: ""
        }, options);

        var ss = $H.session.self;
        if (options.key && ss) {

          if (options.key.length > 64)
            options.key = $H.hash(options.key);

          //浏览器关闭 sessionStorage
          try {
            ss.setItem(options.key, options.value);
          }
          catch (e) { console.error(e); }
        }
      },
      remove: function (key) {
        var ss = $H.session.self;
        if (ss) {
          if (key.length > 64) key = $H.hash(key);

          //浏览器关闭 sessionStorage
          try {
            ss.removeItem(key);
          }
          catch (e) { console.error(e); }
        }
      },
      clear: function () {
      //浏览器关闭 sessionStorage
      try {
        $H.session.self.clear();
      }
      catch (e) { console.error(e); }
    }
  };

  $H.mask = {
    ui: $("<div id='imgBox'>"),
    show: function (options) {
      options = $.extend({
        scrollable: true,
        clickMask: function () { }
      }, options);

            //var height = $(document).height();
            //if ($H.browser.height() > height)
            //    height = $H.browser.height();

            $H.mask.ui.css({
              "background-color": "#333",
              "position": "absolute",
              "top": "0",
              "height": document.body.scrollHeight,
              "width": "100%",
              "z-index": "9998",
              "opacity": ".6"
            }).appendTo($("body"));

            $H.mask.ui.off("tap");
            $H.mask.ui.on("tap", options.clickMask);

            if (!options.scrollable)
              $H.browser.discrollable();

            return $H.mask.ui;
          },
          close: function () {
            if ($H.mask.ui) {
              $H.mask.ui.empty();
              $H.mask.ui.remove();
            }
            $H.browser.scrollable();
          }
        };
        $H.loader = {
          ui: $("<div>").addClass("loader"),
          show: function (options) {
            options = $.extend({
              text: "",
              mask: true,
              scrollable: false,
              clickMask: function () { },
              timeout: -1
            }, options);

            $H.loader.ui.empty();
            var text = $("<div>");
            var loading = $("<div>").addClass("loading");

            if (options.mask) {
              $H.mask.show({
                scrollable: true,
                clickMask: options.clickMask
              });
            }

            loading.appendTo($H.loader.ui);
            $H.loader.ui.appendTo($("body"));

            if (options.text) {
              text.addClass("text").html(options.text).appendTo($H.loader.ui);
            }
            $H.loader.ui.css("margin-left", -$H.loader.ui.width() / 2);

            //todo; 提炼出int解析方法
            //如果不传timeout，则永久显示
            var timeout = parseInt(options.timeout, 10);
            /*        if (!isNaN(timeout) && timeout >= 0)
            setTimeout($H.loader.close, timeout * 1000);*/

            if (!options.scrollable)
              $H.browser.discrollable();

            return $H.loader.ui;
          },
          close: function () {
            $H.mask.close();
            if ($H.loader.ui) {
              $H.loader.ui.empty();
              $H.loader.ui.remove();
            }
          }
        };

        $H.toast = {
          ui: $("<div class='toast'></div>"),
          show: function (options) {
            options = $.extend({
              content: "",
              scrollable: false,
              duration: 2000
            }, options);
            $H.toast.ui.removeClass("t-out t-show").empty();
            if (options.content != "") {
              var span = $("<span class='content'>" + options.content + "</span>");
              $H.toast.ui.html(span);
            };

            $H.toast.ui.appendTo($("body"));
            $H.toast.ui.addClass('t-show')

            if (!options.scrollable)
              $H.browser.discrollable();
            $H.toast.ui.on('webkitAnimationEnd AnimationEnd', function (event) {
              event.preventDefault();
              t = setTimeout(function () {
                $H.toast.ui.addClass("t-out");
                $H.toast.hide();
              }, options.duration)

            });
          },
          hide: function () {
            if ($H.toast.ui) {
              $H.toast.ui.empty();
              $H.toast.ui.remove();
              clearTimeout(t);
            }
            $H.browser.scrollable();
          }

        };

        $H.dialog = {
          ui: $("<div>").addClass("dialog"),
          show: function (options) {
            options = $.extend({
              title: "温馨提示",
              content: "",
              buttons: null,
              mask: false,
              scrollable: false,
              clickMask: function () { }
            }, options);

            $H.dialog.ui.empty();
            var title = $("<div>").addClass("title");
            var content = $("<div>").addClass("content");
            var btns = $("<div>").addClass("btns");

            if (options.mask) {
              $H.mask.show({
                scrollable: true,
                clickMask: options.clickMask
              });
            }

            if (options.title) {
              title.html(options.title);
              $H.dialog.ui.append(title);
            }

            $H.dialog.ui.append(content);
            if (options.content) {
              content.html(options.content).css("max-height", $H.browser.height() - 180);
            }

            //btn = {text:"",callback:"",className:"",css:{}}
            if (options.buttons) {
              $.each(options.buttons, function (index, item) {
                var zepBtn = $("<a href='javascript:void(0)'>").text(item.text);
                    //todo: touchActive
                    zepBtn.on("touchstart mousedown", function (event) {
                      $(this).addClass("active");
                      var This = $(this);
                      if ("android,windowsmobile,windowsphone,windowspc".indexOf($H.os.type()) != -1) {
                        setTimeout(function () { This.removeClass("active"); }, 800);
                      }
                    }).on("touchcancel touchend mouseup click", function () {
                      $(this).removeClass("active");
                    });

                    if (item.className)
                      zepBtn.addClass(item.className);
                    if (item.css)
                      zepBtn.css(item.css);
                    if (item.callback)
                      zepBtn.off("touchend").on("touchend", function (event) {
                        event.stopPropagation();
                        event.preventDefault();
                        item.callback();
                      });
                    btns.append(zepBtn);
                    zepBtn = null;
                  });
              $H.dialog.ui.append(btns);
            }

            $H.dialog.ui.appendTo($("body"));
            $H.dialog.ui.css("margin-top", -$H.dialog.ui.height() / 2);

            if (!options.scrollable)
              $H.browser.discrollable();
            //$H.dialog.content.unbind("touchmove", $H.browser.preventEvent);

            return $H.dialog.ui;
          },
          close: function () {
            $H.mask.close();
            if ($H.dialog.ui) {
              $H.dialog.ui.empty();
              $H.dialog.ui.remove();
            }

            $H.browser.scrollable();
          }
        };

    //lazy load
    $H.lazy = function () {


    };

    return $H;
})();

//精简版的tap事件
(function () {
    var touchTarget, enable = 'ontouchstart' in document,
        tap = { start: enable ? 'touchstart' : 'mousedown', end: enable ? 'touchend' : 'mouseup' },
        cancelTap = function () { touchTarget = undefined; };

    $(document).on(tap.start, function (e) {
        touchTarget = e.target;
    }).on(tap.end, function (e) {
        if (e.target == touchTarget) {
            setTimeout(function () {
                $(touchTarget).trigger("tap");
                cancelTap();
            }, 0);
            e.stopPropagation();
        }
    }).on('touchcancel', cancelTap);
    if (!('MSGesture' in window))
        $(window).on('scroll', cancelTap);
    $.fn.tap = function (fn) { return this.on("tap", fn); };
})();
module.exports = Hobbit;